/**
 * 
 */
package com.dalonedrow.module.chivalrysorcery.systems;

import com.dalonedrow.engine.animation.AnimationSequenceObjectFactory;
import com.dalonedrow.engine.sprite.base.SimpleDimension;
import com.dalonedrow.engine.sprite.base.SimpleVector2;
import com.dalonedrow.engine.sprite.base.SimpleVector3;
import com.dalonedrow.engine.sprite.base.SpriteBase;
import com.dalonedrow.engine.sprite.base.SpriteImageObject;
import com.dalonedrow.engine.sprite.base.SpriteImageObjectFactory;
import com.dalonedrow.engine.sprite.impl.BasicSpriteObject;
import com.dalonedrow.engine.systems.JOGLErrorHandler;
import com.dalonedrow.engine.systems.Render;
import com.dalonedrow.engine.systems.Time;
import com.dalonedrow.engine.systems.base.Animation;
import com.dalonedrow.engine.systems.base.GameState;
import com.dalonedrow.engine.systems.base.InputEvent;
import com.dalonedrow.engine.systems.base.Interactive;
import com.dalonedrow.engine.ui.base.border.Abstract8ImageBorder;
import com.dalonedrow.engine.ui.base.panel.PortraitPagePanel;
import com.dalonedrow.module.chivalrysorcery.constants.ChivalrySorceryConstants;
import com.dalonedrow.module.chivalrysorcery.rpg.ChivSorcInteractiveObject;
import com.dalonedrow.pooled.PooledStringBuilder;
import com.dalonedrow.pooled.StringBuilderPool;
import com.dalonedrow.rpg.base.flyweights.BaseInteractiveObject;
import com.dalonedrow.rpg.base.systems.Inventory;

/**
 * @author Donald
 */
@SuppressWarnings("rawtypes")
public final class ChivSorcInventory extends PortraitPagePanel
		implements Inventory<ChivSorcInteractiveObject> {
	/** the one and only instance of the <code>HQInventory</code> class. */
	private static ChivSorcInventory	instance;
	/**
	 * Gives access to the singleton instance of {@link ChivSorcInventory}.
	 * @return {@link ChivSorcInventory}
	 */
	public static ChivSorcInventory getInstance() {
		if (ChivSorcInventory.instance == null) {
			ChivSorcInventory.instance = new ChivSorcInventory();
		}
		return ChivSorcInventory.instance;
	}
	/** the unequipped inventory slot backgrounds. */
	private SpriteBase[]			emptyBackgrounds;
	/** the equipped inventory slot backgrounds. */
	private SpriteBase[]			equippedBackgrounds;
	/** the GlobalConstants highlight. */
	private BaseInteractiveObject	highlight;
	/** the current player whose inventory is being viewed. */
	private ChivSorcInteractiveObject		player;
	/** the preferred tooltip position. */
	private SimpleVector3					tooltipPosition;
	/**
	 * Creates a new instance of {@link ChivSorcInventory}.
	 */
	private ChivSorcInventory() {
		super.setHandleMouseOverIndependent(true);
		// initialize the view
		// set the border
		int myCols = ChivalrySorceryConstants.INV_SLOTS / ChivalrySorceryConstants.INV_ROWS;
		int myWidth = myCols * ChivalrySorceryConstants.IMG_SIZE;
		// padding between each column
		myWidth += (myCols - 1) * slotPadding;
		if (super.getBorder() != null) {
			myWidth += super.getBorder().getInsets().left;
			myWidth += super.getBorder().getInsets().right;
		}
		int myHeight = ChivalrySorceryConstants.INV_ROWS * ChivalrySorceryConstants.IMG_SIZE;
		// padding between each row
		myHeight += (ChivalrySorceryConstants.INV_ROWS - 1) * slotPadding;
		if (super.getBorder() != null) {
			myHeight += super.getBorder().getInsets().top;
			myHeight += super.getBorder().getInsets().bottom;
		}
		super.setPreferredSize(myWidth, myHeight);
		emptyBackgrounds = new SpriteBase[ChivalrySorceryConstants.INV_SLOTS];
		equippedBackgrounds = new SpriteBase[ChivalrySorceryConstants.INV_SLOTS];
		try {
			for (int i = 0; i < emptyBackgrounds.length; i++) {
				emptyBackgrounds[i] = new BasicSpriteObject();
				SpriteImageObject img =
						SpriteImageObjectFactory.getInstance().getImageByName(
								"hq_ultima_inv_panel_unequipped_bkg");
				emptyBackgrounds[i].setImageRefId(img.getRefId());
				emptyBackgrounds[i].setWidth(img.getWidth());
				emptyBackgrounds[i].setHeight(img.getHeight());

				equippedBackgrounds[i] = new BasicSpriteObject();
				img =
						SpriteImageObjectFactory.getInstance().getImageByName(
								"hq_ultima_inv_panel_equipped_bkg");
				equippedBackgrounds[i].setImageRefId(img.getRefId());
				equippedBackgrounds[i].setWidth(img.getWidth());
				equippedBackgrounds[i].setHeight(img.getHeight());
			}
			highlight =
					(BaseInteractiveObject) Interactive.getInstance()
							.getNewIO();
			SpriteBase sb = new BasicSpriteObject();
			SpriteImageObject img =
					SpriteImageObjectFactory.getInstance().getImageByName(
							"hq_ultima_inv_sel_cursor_0");
			sb.setImageRefId(img.getRefId());
			sb.setWidth(img.getWidth());
			sb.setHeight(img.getHeight());
			highlight.setSprite(sb);
			highlight.addAnimation("selection",
					AnimationSequenceObjectFactory.getInstance()
							.getSequenceRefId("hq_ultima_inv_sel_cursor"));
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	@Override
	public boolean canBePutInInventory(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO) throws Exception {
		if (item == null) {
			return false;
		}
		if (item.hasIOFlag(ChivalrySorceryConstants.IO_15_MOVABLE)) {
			return false;
		}
		if (item.hasIOFlag(ChivalrySorceryConstants.IO_10_GOLD)) {
			ChivSorcPlayer.getInstance().addGold(playerIO,
					item.getItemData().getPrice());
			if (item.isScriptLoaded()) {
				removeFromAllInventories(playerIO, item);
				Interactive.getInstance().releaseIO(item);
			} else {
				item.setShow(GlobalConstants.SHOW_FLAG_KILLED);
				item.removeGameFlag(GlobalConstants.GFLAG_ISINTREATZONE);
			}
			return true;
		}
		// find an empty slot
		if (playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = playerIO.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					if (inventory.getSlot(i).getIo() == null) {
						inventory.getSlot(i).setIo(item);
						inventory.getSlot(i).setShow(true);
						declareInInventory(item, playerIO);
						return true;
					}
				}
			}
		}
		return false;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void checkForInventoryReplaceMe(final ChivSorcInteractiveObject item1,
			final ChivSorcInteractiveObject item2,
			final ChivSorcInteractiveObject playerIO) throws Exception {
		boolean done = false;
		// check to see if item replaced is coming from player's inventory
		HQInventoryData inventory = playerIO.getInventory();
		if (inventory != null) {
			for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
				if (inventory.getSlot(i).getIo().equals(item2)) {
					if (canBePutInInventory(item1, playerIO)) {
						done = true;
						break;
					}
					putInFrontOfPlayer(item1, playerIO, true);
					done = true;
					break;
				}
			}
		}
		if (!done) {
			// check to see if another IO is swapping with player
			for (int i = 0; i < Interactive.getInstance().getNumberIOs(); i++) {
				if (Interactive.getInstance().hasIO(i)) {
					ChivSorcInteractiveObject hio =
							(ChivSorcInteractiveObject) Interactive.getInstance()
									.getIO(i);
					if (hio.getInventory() != null) {
						HQInventoryData id = hio.getInventory();
						for (int j = 0; j < id.getNumInventorySlots(); j++) {
							if (id.getSlot(j).getIo().equals(item2)) {
								if (canBePutInInventory(item1, hio)) {
									done = true;
									break;
								}
								putInFrontOfPlayer(item1, playerIO, true);
								done = true;
								break;
							}
						}
					}
				}
				if (done) {
					break;
				}
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void cleanInventory(final ChivSorcInteractiveObject playerIO) {
		if (playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = playerIO.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					inventory.getSlot(i).setIo(null);
					inventory.getSlot(i).setShow(true);
				}
			}
		}
	}
	/** Clears the highlight GlobalConstants. */
	public void clearHighlight() {
		if (highlight != null) {
			Animation.getInstance().stopAllAnimations(highlight);
			highlight.getSprite().setPosition(null);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void declareInInventory(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO) throws Exception {
		if (item != null
				&& playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQScript.getInstance().setEventSender(item);
			HQScript.getInstance().sendIOScriptEvent(
					playerIO, GlobalConstants.SM_002_INVENTORYIN, null, null);
			HQScript.getInstance().setEventSender(playerIO);
			HQScript.getInstance().sendIOScriptEvent(
					item, GlobalConstants.SM_002_INVENTORYIN, null, null);
			HQScript.getInstance().setEventSender(null);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean dragSuccessful() {
		// NOT USED
		return false;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void dropItem(final ChivSorcInteractiveObject ioSource,
			final ChivSorcInteractiveObject ioItem, final boolean inSameSpot) {
		if (ioSource != null
				&& ioSource.getPosition() != null
				&& ioItem != null) {
			if (inSameSpot) {
				HQMap.getInstance().addIOToMap(
						(float) ioSource.getPosition().getX(),
						(float) ioSource.getPosition().getY(),
						ioItem.getRefId()
						);
			} else {
				int facing = GlobalConstants.DIR_00_NORTH;
				if (ioSource.hasIOFlag(GlobalConstants.IO_01_PC)) {
					facing = ioSource.getPCData().getDirectionFacing();
				}
				int orig = facing;
				// start at facing
				boolean done = false;
				while (!done) {
					float x = (float) ioSource.getPosition().getX();
					float y = (float) ioSource.getPosition().getY();
					switch (facing) {
					case GlobalConstants.DIR_00_NORTH:
						y++;
						break;
					case GlobalConstants.DIR_02_EAST:
						x++;
						break;
					case GlobalConstants.DIR_04_SOUTH:
						y--;
						break;
					case GlobalConstants.DIR_06_WEST:
						x--;
						break;
					default:
						break;
					}
					if (!putOnMap(x, y, ioItem)) {
						facing++;
						if (facing > GlobalConstants.DIR_07_NORTH_WEST) {
							facing = 0;
						}
						if (facing == orig) {
							// if we get back to original direction
							// put the item at the pc's location
							putOnMap(
									(float) ioSource.getPosition().getX(),
									(float) ioSource.getPosition().getY(),
									ioItem);
							done = true;
						}
					}
				}

			}
		}
	}
	private String getDescriptionString(final ChivSorcInteractiveObject io)
			throws Exception {
		PooledStringBuilder sb = StringBuilderPool.getInstance()
				.getStringBuilder();
		sb.append(io.getItemData().getItemName());
		sb.append("\n");
		if (player != null) {
			if (ChivSorcEquipment.getInstance().isPlayerEquippedWithItem(
					player, io)) {
				sb.append("*EQUIPPED*\n");
			}
		} else {
			sb.append("\n");
		}
		sb.append(io.getItemData().getDescription());
		String t = sb.toString();
		sb.returnToPool();
		return t;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public ChivSorcInteractiveObject getInventoryObject(final float x,
			final float y) {
		ChivSorcInteractiveObject io = null;
		if (player != null
				&& player.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = player.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					SimpleVector3 slot = getSlotPosition(i, 0);
					if (slotContains(slot.getX(), slot.getY(), x, y)) {
						io = inventory.getSlot(i).getIo();
						break;
					}
				}
			}
		}
		return io;
	}
	/**
	 * {@inheritDoc}
	 */
	public ChivSorcInteractiveObject getInventoryObject(
			final ChivSorcInteractiveObject playerIO, final int slot) {
		ChivSorcInteractiveObject io = null;
		if (playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)
				&& playerIO.getInventory() != null) {
			io = playerIO.getInventory().getSlot(slot).getIo();
		}
		return io;
	}
	public int getInventorySlotForPosition(final float x, final float y) {
		int slot = -1;
		if (player != null
				&& player.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = player.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					SimpleVector3 pos = getSlotPosition(i, 0);
					if (slotContains(pos.getX(), pos.getY(), x, y)) {
						slot = i;
						break;
					}
				}
			}
		}
		return slot;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public ChivSorcInteractiveObject getPlayerViewed() {
		return player;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public SimpleDimension getPreferredSizeWhenDisplayingTooltip() {
		return new SimpleDimension(GlobalConstants.IMG_SIZE, GlobalConstants.IMG_SIZE);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public SimpleDimension getPreferredSize() {
		int myCols = GlobalConstants.INV_SLOTS / GlobalConstants.INV_ROWS;
		int myWidth = myCols * GlobalConstants.IMG_SIZE;
		// padding between each column
		myWidth += (myCols - 1) * slotPadding;
		int myHeight = GlobalConstants.INV_ROWS * GlobalConstants.IMG_SIZE;
		// padding between each row
		myHeight += (GlobalConstants.INV_ROWS - 1) * slotPadding;
		if (super.getBorder() != null) {
			myWidth += super.getBorder().getInsets().left;
			myWidth += super.getBorder().getInsets().right;
			myHeight += super.getBorder().getInsets().top;
			myHeight += super.getBorder().getInsets().bottom;
		}
		super.setPreferredSize(myWidth, myHeight);
		return super.getPreferredSize();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public SimpleVector3 getPreferredTooltipPosition() {
		SimpleVector3 pos = tooltipPosition;
		if (pos == null) {
			pos = super.getPosition();
		}
		return pos;
	}
	/** the padding between inventory slots. */
	private final int slotPadding = 1;
	/**
	 * Gets the screen position of a specific inventory slot.
	 * @param index the inventory slot
	 * @param zMod any modification the the z-axis applied
	 * @return {@link SimpleVector3}
	 */
	public SimpleVector3 getSlotPosition(final int index, final float zMod) {
		// the number of columns displayed
		int myCols = GlobalConstants.INV_SLOTS / GlobalConstants.INV_ROWS;
		// x starts out at the left-side of the widget
		float x = (float) super.getPosition().getX();
		if (super.getBorder() != null) {
			x += super.getBorder().getInsets().left;
		}
		float y = (float) super.getPosition().getY();
		if (super.getBorder() != null) {
			y += super.getBorder().getInsets().bottom;
		}
		float z = (float) super.getPosition().getZ();
		z += (float) GlobalConstants.CHILD_STEP * zMod;
		// find out column of index
		float colNum = index % myCols;
		x += colNum * GlobalConstants.IMG_SIZE;
		x += colNum * slotPadding;

		y += GlobalConstants.IMG_SIZE * (GlobalConstants.INV_ROWS - 1);
		y += slotPadding * (GlobalConstants.INV_ROWS - 1);
		
		// find out row number
		int rowNum = index / myCols;
		y -= rowNum * GlobalConstants.IMG_SIZE;
		y -= slotPadding * rowNum;
		return new SimpleVector3(x, y, z);
	}
	/**
	 * Shows the equipment dialog for a specific slot.
	 * @param slot the slot
	 * @throws Exception if an exception occurs
	 */
	public void showEquipmentDialog(final int slot) throws Exception {
			clearHighlight();
			EquipmentDialog.getInstance().showDialog(slot);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean touchUp(final int x, final int y, final int pointer, 
			final int button) {
		ChivSorcInteractiveObject io = getInventoryObject(x, y);
		int state = GameState.getInstance().getCurrentState();
		if (state != GameState.STATE_14HQ_CHAR_CHOOSER
				&& io != null) {
			try {
				InputEvent.getInstance().addAction(
						ChivSorcInventory.getInstance(), // object
						ChivSorcInventory.getInstance().getClass().getMethod(
								"showEquipmentDialog", 
								new Class[] { int.class }),
						new Integer[] { getInventorySlotForPosition(x, y) }
						);
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
		}
		return true;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleMouseOver(final float x, final float y) {
		ChivSorcInteractiveObject io = getInventoryObject(x, y);
		if (io != null) {
			// play selection GlobalConstants
			try {
				if (GameState.getInstance().getCurrentState() 
						!= GameState.STATE_14HQ_CHAR_CHOOSER) {
					HQController.getInstance().setCursor(GlobalConstants.CURSOR_12_HAND);
				} else {
					HQController.getInstance().setCursor(GlobalConstants.CURSOR_00_DEFAULT);
				}
				String ttText = getDescriptionString(io);
				int slot = getInventorySlotForPosition(x, y);
				tooltipPosition = getSlotPosition(slot, 0);
				highlight.getSprite().setPosition(getSlotPosition(slot, 3));
				Animation.getInstance().playAnimation(highlight,
						highlight.getAnimation("selection"));

				// set tooltip
				if (ttText.equalsIgnoreCase(super.getTooltipText())) {
					// already started tooltip for this item
					if (super.hasTooltipTimerStarted()) {
						// check to see if it's time
						// to display the tooltip
						super.updateTooltipTimer(
								Time.getInstance().getGameTime());
					} else { // start the tooltip timer
						super.startTooltipTimer(
								Time.getInstance().getGameTime());
					}
				} else {
					// set new tooltip text
					super.setTooltipText(ttText);
					// stop previous tooltips
					if (super.hasTooltipTimerStarted()) {
						// panel has tooltip - stop them
						super.stopTooltipTimer();
					}
					// start tooltip for this item
					super.startTooltipTimer(Time.getInstance().getGameTime());
				}
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
		} else {
			Animation.getInstance().stopAllAnimations(highlight);
			highlight.getSprite().setPosition(null);
			tooltipPosition = null;
			super.setTooltipText(null);
			if (super.hasTooltipTimerStarted()) {
				// panel has tooltip - stop them
				super.stopTooltipTimer();
			}
			HQController.getInstance().setCursor(GlobalConstants.CURSOR_00_DEFAULT);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void identifyAll(final ChivSorcInteractiveObject playerIO) {
		if (playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = playerIO.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					ChivSorcInteractiveObject io = inventory.getSlot(i).getIo();
					if (io != null
							&& io.hasIOFlag(GlobalConstants.IO_02_ITEM)
							&& io.getItemData() != null
							&& io.getItemData().getEquipitem() != null) {
						// in arx, this is where the player's object knowledge
						// and mind attribute were checked against the item's
						// identify value.
						// if the item could be identified, an event was sent to
						// the script.
					}
				}
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void identifyItem(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO) {
		// DO NOTHING. NO UNIDENTIFIED ITEMS IN GAME
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean isInPlayerInventory(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO) {
		boolean isin = false;
		if (item != null
				&& playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = playerIO.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					ChivSorcInteractiveObject io = inventory.getSlot(i).getIo();
					if (io != null
							&& io.equals(item)) {
						isin = true;
						break;
					}
				}
			}
		}
		return isin;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareForRendering() throws Exception {
		super.prepareForRendering();
		if (super.isVisible()) {
			// check inventory slots
			if (player != null) {
				HQInventoryData inventory = player.getInventory();
				if (inventory != null) {
					for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
						boolean doEmpty = true;
						ChivSorcInteractiveObject io = inventory.getSlot(i).getIo();
						if (io != null
								&& io.hasIOFlag(GlobalConstants.IO_02_ITEM)) {
							io.getSprite().setPosition(getSlotPosition(i, 2));
							Render.getInstance().registerEntity(io.getSprite());
						}
						if (ChivSorcEquipment.getInstance()
								.isPlayerEquippedWithItem(player, io)) {
							doEmpty = false;
						}
						if (doEmpty) {
							emptyBackgrounds[i].setPosition(
									getSlotPosition(i, 1));
							Render.getInstance().registerEntity(
									emptyBackgrounds[i]);
						} else {
							equippedBackgrounds[i].setPosition(
									getSlotPosition(i, 1));
							Render.getInstance().registerEntity(
									equippedBackgrounds[i]);
						}
					}
					if (highlight.getSprite().getPosition() != null) {
						Render.getInstance().registerEntity(
								highlight.getSprite());
					}
				}
			} else {
				// player was never set. display all empty
				for (int i = emptyBackgrounds.length - 1; i >= 0; i--) {
					emptyBackgrounds[i].setPosition(getSlotPosition(i, 1));
					Render.getInstance().registerEntity(emptyBackgrounds[i]);
				}
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void putInFrontOfPlayer(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO, final boolean applyPhysics) {
		// find the direction the player is facing
		if (item != null
				&& playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQCharacter pc = playerIO.getPCData();
			int facing = pc.getDirectionFacing();
			// start at facing
			boolean done = false;
			while (!done) {
				float x = (float) playerIO.getPosition().getX();
				float y = (float) playerIO.getPosition().getY();
				switch (facing) {
				case GlobalConstants.DIR_00_NORTH:
					y++;
					break;
				case GlobalConstants.DIR_02_EAST:
					x++;
					break;
				case GlobalConstants.DIR_04_SOUTH:
					y--;
					break;
				case GlobalConstants.DIR_06_WEST:
					x--;
					break;
				default:
					break;
				}
				if (!putOnMap(x, y, item)) {
					facing++;
					if (facing > GlobalConstants.DIR_07_NORTH_WEST) {
						facing = 0;
					}
					if (facing == pc.getDirectionFacing()) {
						// if we get back to original direction
						// put the item at the pc's location
						putOnMap(
								(float) playerIO.getPosition().getX(),
								(float) playerIO.getPosition().getY(),
								item);
						done = true;
					}
				}
			}
		}
	}
	/**
	 * Attempts to place an item on the game map.
	 * @param x the x position
	 * @param y the y position
	 * @param item the item
	 * @return true if the item was placed on the map; false otherwise
	 */
	private boolean putOnMap(final float x, final float y,
			final ChivSorcInteractiveObject item) {
		boolean done = false;
		try {
		if (HQMap.getInstance().hasCellAt(x, y + 1)) {
			HQMap.getInstance().addIOToMap(x, y, item.getRefId());
			done = true;
		}
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
		return done;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void removeFromAllInventories(final ChivSorcInteractiveObject item,
			final ChivSorcInteractiveObject playerIO) throws Exception {
		if (item != null) {
			HQInventoryData id;
			// Seek IO in Player Inventory/ies
			if (playerIO != null
					&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
				HQInventoryData inventory = playerIO.getInventory();
				if (inventory != null) {
					for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
						if (item.equals(inventory.getSlot(i).getIo())) {
							inventory.getSlot(i).setIo(null);
							inventory.getSlot(i).setShow(true);
						}
					}
				}
			}
			// Seek IO in Other IO's Inventories
			for (int i = 0; i < Interactive.getInstance().getNumberIOs(); i++) {
				ChivSorcInteractiveObject io = null;
				if (Interactive.getInstance().hasIO(i)) {
					io = (ChivSorcInteractiveObject) Interactive.getInstance().getIO(
							i);
				}
				if (io != null) {
					if (io.getInventory() != null) {
						id = io.getInventory();
						for (int j = 0; j < id.getNumInventorySlots(); j++) {
							if (item.equals(id.getSlot(j).getIo())) {
								id.getSlot(j).setIo(null);
								id.getSlot(j).setShow(true);
							}
						}
					}
				}
			}
			id = null;
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void replaceInAllInventories(final ChivSorcInteractiveObject item1,
			final ChivSorcInteractiveObject item2, final ChivSorcInteractiveObject playerIO)
			throws Exception {
		if (item1 == null || item2 == null) {
			return;
		}

		int ion = item1.getRefId();
		int ioon = item2.getRefId();
		ChivSorcInteractiveObject hion =
				(ChivSorcInteractiveObject) Interactive.getInstance()
						.getIO(ion);
		ChivSorcInteractiveObject hioon =
				(ChivSorcInteractiveObject) Interactive.getInstance()
						.getIO(ioon);
		HQInventoryData inventory = playerIO.getInventory();
		if (inventory != null) {
			for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
				if (inventory.getSlot(i).getIo().equals(hion)) {
					inventory.getSlot(i).setIo(hioon);
				}
			}
		}
		for (int i = 0; i < Interactive.getInstance().getNumberIOs(); i++) {
			if (Interactive.getInstance().hasIO(i)) {
				ChivSorcInteractiveObject hio =
						(ChivSorcInteractiveObject) Interactive.getInstance()
								.getIO(i);
				if (!hio.equals(hion)) {
					if (hio.getInventory() != null) {
						HQInventoryData id = hio.getInventory();
						for (int j = 0; j < id.getNumInventorySlots(); j++) {
							if (id.getSlot(j).getIo().equals(hion)) {
								id.getSlot(j).setIo(hioon);
							}
						}
					}
				}
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void sendInventoryObjectCommand(final String itemName,
			final int commandId, final ChivSorcInteractiveObject playerIO)
			throws Exception {
		if (itemName != null
				&& itemName.length() > 0
				&& playerIO != null
				&& playerIO.hasIOFlag(GlobalConstants.IO_01_PC)) {
			HQInventoryData inventory = playerIO.getInventory();
			if (inventory != null) {
				for (int i = 0; i < inventory.getNumInventorySlots(); i++) {
					ChivSorcInteractiveObject io = inventory.getSlot(i).getIo();
					if (io != null
							&& io.hasIOFlag(GlobalConstants.IO_02_ITEM)
							&& io.getItemData() != null
							&& io.getItemData().getEquipitem() != null
							&& io.getItemData().getItemName().equals(itemName)) {
						if (io.hasIOFlag(GlobalConstants.IO_11_INTERACTIVITY)) {
							HQScript.getInstance().sendIOScriptEvent(
									io, commandId, null, null);
						}
					}
				}
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPlayerViewed(final ChivSorcInteractiveObject playerIO) {
		player = playerIO;
	}
	/**
	 * Determines if the slot contains a specific point.
	 * @param x0 the slot's left side
	 * @param y0 the slot's bottom side
	 * @param x1 the point's x-position
	 * @param y1 the point's y-position
	 * @return true if the slot contains the point; false otherwise
	 */
	private boolean slotContains(final double x0, final double y0, 
			final double x1, final double y1) {
		return x1 >= x0
				&& y1 >= y0
				&& x1 < x0 + GlobalConstants.IMG_SIZE
				&& y1 < y0 + GlobalConstants.IMG_SIZE;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean takeFromInventory(SimpleVector2 pos, ChivSorcInteractiveObject playerIO) {
		// TODO Auto-generated method stub
		return false;
	}
}
